using System;
using UnityEngine;
using UnityEngine.InputSystem;

namespace MinesweeperPlus.Scripts.Objects
{
    public class PlayerInput
    {
        #region Actions
        public Action<Vector2, float> OnStartFirstTouch;
        public Action<Vector2, float> OnHoldFirstTouch;
        public Action<Vector2, float> OnEndFirstTouch;

        public Action<Vector2, float> OnStartSecondTouch;
        public Action<Vector2, float> OnHoldSecondTouch;
        public Action<Vector2, float> OnEndSecondTouch;
        #endregion

        #region Variables
        private Game _game;
        private TouchControls _touchControls;
        private bool _isActive;
        private float _firstTouchDuration;
        private float _secondTouchDuration;

        private InputAction _firstTouchContact => _touchControls.Touch.FirstTouchContact;
        private InputAction _firstTouchPosition => _touchControls.Touch.FirstTouchPosition;

        private InputAction _secondTouchContact => _touchControls.Touch.SecondTouchContact;
        private InputAction _secondTouchPosition => _touchControls.Touch.SecondTouchPosition;
        #endregion
        #region Properties
        public bool IsActive
        {
            get => _isActive;
            set 
            {
                if (_isActive == value)
                    return;

                _isActive = value;
                if (_isActive)
                    _touchControls.Enable();
                else
                    _touchControls.Disable();
            }
        }
        
        public bool IsFisrtTouchHolded { get; private set; }
        public Vector2 FirstTouchScreenPosition { get; private set; }
        public bool IsSecondTouchHolded { get; private set; }
        public Vector2 SecondTouchScreenPosition { get; private set; }
        #endregion

        #region PlayerInput Methods
        public PlayerInput(Game game)
        {
            _game = game;
            _touchControls = new();
            
            _firstTouchContact.started += StartFirstTouch;
            _firstTouchContact.canceled += EndFirstTouch;
            
            _secondTouchContact.started += StartSecondTouch;
            _secondTouchContact.canceled += EndSecondTouch;
        }
        #endregion

        #region Other Methods
        private void StartFirstTouch(InputAction.CallbackContext context)
        {
            FirstTouchScreenPosition = _firstTouchPosition.ReadValue<Vector2>();
            OnStartFirstTouch?.Invoke(FirstTouchScreenPosition, (float)context.startTime);
            
            _game.OnUpdate += HoldFirstTouch;
            IsFisrtTouchHolded = true;
        }
        private void HoldFirstTouch(float time)
        {
            FirstTouchScreenPosition = _firstTouchPosition.ReadValue<Vector2>();
            _firstTouchDuration += time;
            OnHoldFirstTouch?.Invoke(FirstTouchScreenPosition, _firstTouchDuration);
        }
        private void EndFirstTouch(InputAction.CallbackContext context)
        {
            _game.OnUpdate -= HoldFirstTouch;
            IsFisrtTouchHolded = false;
            _firstTouchDuration = 0;

            FirstTouchScreenPosition = _firstTouchPosition.ReadValue<Vector2>();
            var duration = (float)(context.time - context.startTime);
            OnEndFirstTouch?.Invoke(FirstTouchScreenPosition, duration);   
        }

        private void StartSecondTouch(InputAction.CallbackContext context)
        {
            SecondTouchScreenPosition = _secondTouchPosition.ReadValue<Vector2>();
            OnStartSecondTouch?.Invoke(SecondTouchScreenPosition, (float)context.startTime);

            IsSecondTouchHolded = true;
            _game.OnUpdate += HoldSecondTouch;
        }
        private void HoldSecondTouch(float time)
        {
            SecondTouchScreenPosition = _secondTouchPosition.ReadValue<Vector2>();
            _secondTouchDuration += time;
            OnHoldSecondTouch?.Invoke(SecondTouchScreenPosition, _secondTouchDuration);
        }
        private void EndSecondTouch(InputAction.CallbackContext context)
        {
            _game.OnUpdate -= HoldSecondTouch;
            IsSecondTouchHolded = false;
            _secondTouchDuration = 0;

            SecondTouchScreenPosition = _secondTouchPosition.ReadValue<Vector2>();
            var duration = (float)(context.time - context.startTime);
            OnEndSecondTouch?.Invoke(SecondTouchScreenPosition, duration); 
        }
        #endregion
    }
}
